/* Copyright Statement:
 *
 * This software/firmware and related documentation ("AutoChips Software") are
 * protected under relevant copyright laws. The information contained herein is
 * confidential and proprietary to AutoChips Inc. and/or its licensors. Without
 * the prior written permission of AutoChips inc. and/or its licensors, any
 * reproduction, modification, use or disclosure of AutoChips Software, and
 * information contained herein, in whole or in part, shall be strictly
 * prohibited.
 *
 * AutoChips Inc. (C) 2023. All rights reserved.
 *
 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("AUTOCHIPS SOFTWARE")
 * RECEIVED FROM AUTOCHIPS AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
 * ON AN "AS-IS" BASIS ONLY. AUTOCHIPS EXPRESSLY DISCLAIMS ANY AND ALL
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NONINFRINGEMENT. NEITHER DOES AUTOCHIPS PROVIDE ANY WARRANTY WHATSOEVER WITH
 * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
 * INCORPORATED IN, OR SUPPLIED WITH THE AUTOCHIPS SOFTWARE, AND RECEIVER AGREES
 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN AUTOCHIPS
 * SOFTWARE. AUTOCHIPS SHALL ALSO NOT BE RESPONSIBLE FOR ANY AUTOCHIPS SOFTWARE
 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND AUTOCHIPS'S
 * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE AUTOCHIPS SOFTWARE
 * RELEASED HEREUNDER WILL BE, AT AUTOCHIPS'S OPTION, TO REVISE OR REPLACE THE
 * AUTOCHIPS SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
 * CHARGE PAID BY RECEIVER TO AUTOCHIPS FOR SUCH AUTOCHIPS SOFTWARE AT ISSUE.
 */

/*!
 * @file ac780x_can_reg.h
 *
 * @brief CAN access register inline function definition.
 *
 */

#ifndef _AC780X_CAN_REG_H
#define _AC780X_CAN_REG_H

#ifdef __cplusplus
extern "C" {
#endif

/* ===========================================  Includes  =========================================== */
#include "ac780x_can.h"

/* ======================================  Functions define  ======================================== */
/*!
 * @brief Set CANx reset state.
 *
 * @param[in] CANx: CAN module
 * @param[in] state: enable state
 *              - ENABLE
 *              - DISABLE
 * @return none
 */
__STATIC_INLINE void CAN_SetReset(CAN_Type *CANx, ACTION_Type state)
{
    MODIFY_REG32(CANx->CTRL0, CAN_CTRL0_RESET_Msk, CAN_CTRL0_RESET_Pos, state);
}

/*!
 * @brief Get software reset state.
 *
 * @param[in] CANx: CAN module
 * @return Reset state
 */
__STATIC_INLINE uint8_t CAN_GetResetState(CAN_Type *CANx)
{
    return (((CANx->CTRL0 & CAN_CTRL0_RESET_Msk) >> CAN_CTRL0_RESET_Pos) != 0U);
}

/*!
 * @brief Set transceiver standby state.
 *
 * @param[in] CANx: CAN module
 * @param[in] state: enable state
 *              - ENABLE
 *              - DISABLE
 * @return 0: success, 1: standby error
 */
__STATIC_INLINE int32_t CAN_SetStandby(CAN_Type *CANx, ACTION_Type state)
{
    int32_t err = 0;

    if (state)
    {
        /* If there is any transmission, can not entry standby mode */
        if (!(CANx->CTRL0 & (CAN_CTRL0_TPE_Msk | CAN_CTRL0_TSONE_Msk | CAN_CTRL0_TSALL_Msk)))
        {
            CANx->CTRL0 |= CAN_CTRL0_STBY_Msk;
        }
        else
        {
            err = 1;
        }
    }
    else
    {
        CANx->CTRL0 &= (~CAN_CTRL0_STBY_Msk);
    }
    
    return err;
}

/*!
 * @brief CAN start transmission.
 *
 * @param[in] CANx: CAN module
 * @param[in] type: CAN transmit type
 *              - CAN_TRANSMIT_PRIMARY
 *              - CAN_TRANSMIT_SECONDARY
 * @param[in] amount: Transmit Secondary ALL or ONE frames
 *              - CAN_TRANSMIT_ALL
 *              - CAN_TRANSMIT_ONE
 * @return none
 */
__STATIC_INLINE void CAN_StartTransmission(CAN_Type *CANx, CAN_TransmitBufferType type, CAN_TransmitAmountType amount)
{
    if (CAN_TRANSMIT_PRIMARY == type)
    {
        CANx->CTRL0 = ((CANx->CTRL0 & (~(CAN_CTRL0_TSNEXT_Msk | CAN_CTRL0_TSALL_Msk | CAN_CTRL0_TSONE_Msk))) | CAN_CTRL0_TPE_Msk);
    }
    else
    {
        if (CAN_TRANSMIT_ONE == amount)
        {
            CANx->CTRL0 = ((CANx->CTRL0 & (~(CAN_CTRL0_TSNEXT_Msk | CAN_CTRL0_TPE_Msk))) | CAN_CTRL0_TSONE_Msk);    /*!< Send one message only */
        }
        else
        {
            CANx->CTRL0 = ((CANx->CTRL0 & (~(CAN_CTRL0_TSNEXT_Msk | CAN_CTRL0_TPE_Msk))) | CAN_CTRL0_TSALL_Msk);    /*!< Send all messages */
        }
    }
}

/*!
 * @brief CAN Abort transmission
 *
 * @param[in] CANx: CAN module
 * @param[in] type: CAN transmit type
 *              - CAN_TRANSMIT_PRIMARY
 *              - CAN_TRANSMIT_SECONDARY
 * @return none
 */
__STATIC_INLINE void CAN_AbortTransmission(CAN_Type *CANx, CAN_TransmitBufferType type)
{
    if (CAN_TRANSMIT_PRIMARY == type)
    {
        CANx->CTRL0 |= CAN_CTRL0_TPA_Msk;
    }
    else
    {
        CANx->CTRL0 |= CAN_CTRL0_TSA_Msk;
    }
}

/*!
 * @brief Check transmission is busy.
 *
 * @param[in] CANx: CAN module
 * @param[in] type: CAN transmit type
 *              - CAN_TRANSMIT_PRIMARY
 *              - CAN_TRANSMIT_SECONDARY
 * @return Transmit busy flag (0: not busy, 1: busy)
 */
__STATIC_INLINE int32_t CAN_IsTransmitBusy(CAN_Type *CANx, CAN_TransmitBufferType type)
{
    if (CAN_TRANSMIT_PRIMARY == type)
    {
        /*!< Transmitting is not successful */
        return (1U == ((CANx->CTRL0 & CAN_CTRL0_TPE_Msk) >> CAN_CTRL0_TPE_Pos));
    }
    else
    {
        /*!< Transmission buffers are full */
        return (CAN_TSSTAT_FULL == ((CANx->CTRL0 & CAN_CTRL0_TSSTAT_Msk) >> CAN_CTRL0_TSSTAT_Pos));
    }
}

/*!
 * @brief Check whether is transmitting.
 *
 * @param[in] CANx: CAN module
 * @param[in] type: CAN transmit type
 *              - CAN_TRANSMIT_PRIMARY
 *              - CAN_TRANSMIT_SECONDARY
 * @return Transmitting status (0: not transmitting, 1: transmitting)
 */
__STATIC_INLINE int32_t CAN_IsTransmitting(CAN_Type *CANx, CAN_TransmitBufferType type)
{
    if (CAN_TRANSMIT_PRIMARY == type)
    {
        return ((CANx->CTRL0 & CAN_CTRL0_TPE_Msk) >> CAN_CTRL0_TPE_Pos);
    }
    else
    {
        return ((CANx->CTRL0 & (CAN_CTRL0_TSALL_Msk | CAN_CTRL0_TSONE_Msk)) != 0U);
    }
}

/*!
 * @brief Check transmission is idle.
 *
 * @param[in] CANx: CAN module
 * @param[in] type: CAN transmit type
 *              - CAN_TRANSMIT_PRIMARY
 *              - CAN_TRANSMIT_SECONDARY
 * @return Transmit idle flag (0: busy, 1: idle)
 */
__STATIC_INLINE int32_t CAN_IsTransmitIdle(CAN_Type *CANx, CAN_TransmitBufferType type)
{
    if (CAN_TRANSMIT_PRIMARY == type)
    {
        return (0U == (CANx->CTRL0 & CAN_CTRL0_TPE_Msk));        /*!< PTB is empty */
    }
    else
    {
        return (0U == (CANx->CTRL0 & CAN_CTRL0_TSSTAT_Msk));     /*!< STB are empty */
    }
}

/*!
 * @brief Check bus off status.
 *
 * @param[in] CANx: CAN module
 * @return Bus off status
 */
__STATIC_INLINE int32_t CAN_IsBusoff(CAN_Type *CANx)
{
    return (CANx->CTRL0 & CAN_CTRL0_BUSOFF_Msk);
}

/*!
 * @brief Forced exit from bus off status.
 *
 * @param[in] CANx: CAN module
 * @return none
 */
__STATIC_INLINE void CAN_ExitBusOff(CAN_Type *CANx)
{
    CANx->CTRL0 &= ~CAN_CTRL0_BUSOFF_Msk;
}

/*!
 * @brief Set CAN interrupt enable.
 *
 * @param[in] CANx: CAN module
 * @param[in] intEn: CAN interrupt enable
 * @return none
 */
__STATIC_INLINE void CAN_SetIntEnable(CAN_Type *CANx, uint32_t intEn)
{
    MODIFY_REG32(CANx->CTRL1, CAN_IRQ_ALL_ENABLE_MSK, 0, intEn);
}

/*!
 * @brief Set CAN error warning limit.
 *
 * @param[in] CANx: CAN module
 * @param[in] ewl: error warning limit
 *          - (0-15)
 * @return none
 */
__STATIC_INLINE void CAN_SetEwl(CAN_Type *CANx, uint8_t ewl)
{
    MODIFY_REG32(CANx->CTRL1, CAN_CTRL1_EWL_Msk, CAN_CTRL1_EWL_Pos, ewl);
}

/*!
 * @brief Set CAN almost full warning limit.
 *
 * @param[in] CANx: CAN module
 * @param[in] afwl: almost full warning limit
 * @return none
 */
__STATIC_INLINE void CAN_SetAfwl(CAN_Type *CANx, uint8_t afwl)
{
    MODIFY_REG32(CANx->CTRL1, CAN_CTRL1_AFWL_Msk, CAN_CTRL1_AFWL_Pos, afwl);
}

/*!
 * @brief Set controller 1 register.
 *
 * @param[in] CANx: CAN module
 * @param[in] value: CAN controller 1 register value
 * @return none
 */
__STATIC_INLINE void CAN_SetCtrl1(CAN_Type *CANx, uint32_t value)
{
    CANx->CTRL1 = value;
}

/*!
 * @brief Get CAN controller 1 register.
 *
 * @param[in] CANx: CAN module
 * @return Controller 1 register value
 */
__STATIC_INLINE uint32_t CAN_GetCtrl1(CAN_Type *CANx)
{
    return CANx->CTRL1;
}

/*!
 * @brief Get CAN transmission time stamp.
 *
 * @param[in] CANx: CAN module
 * @return transmission time stamp
 */
__STATIC_INLINE uint32_t CAN_GetTts(CAN_Type *CANx)
{
    return (CANx->TTS[0]);
}

/*!
 * @brief Enable CAN transmit PTB single shot mode.
 *
 * @param[in] CANx: CAN module
 * @param[in] state: enable state
 *              - ENABLE
 *              - DISABLE
 * @return none
 */
__STATIC_INLINE void CAN_SetTpss(CAN_Type *CANx, ACTION_Type state)
{
    MODIFY_REG32(CANx->CTRL0, CAN_CTRL0_TPSS_Msk, CAN_CTRL0_TPSS_Pos, state);
}

/*!
 * @brief Enable CAN transmit STB single shot mode.
 *
 * @param[in] CANx: CAN module
 * @param[in] state: enable state
 *              - ENABLE
 *              - DISABLE
 * @return none
 */
__STATIC_INLINE void CAN_SetTsss(CAN_Type *CANx, ACTION_Type state)
{
    MODIFY_REG32(CANx->CTRL0, CAN_CTRL0_TSSS_Msk, CAN_CTRL0_TSSS_Pos, state);
}

/*!
 * @brief Get CAN Transmit secondary status.
 *
 * @param[in] CANx: CAN module
 * @return Transmit secondary status
 */
__STATIC_INLINE uint32_t CAN_GetTSStat(CAN_Type *CANx)
{
    return ((CANx->CTRL0 & CAN_CTRL0_TSSTAT_Msk) >> CAN_CTRL0_TSSTAT_Pos);
}

/*!
 * @brief Get transmit secondary buffer full flag.
 *
 * @param[in] CANx: CAN module
 * @return Transmit secondary buffer full flag
 */
__STATIC_INLINE uint8_t CAN_GetTsbufFullFlag(CAN_Type *CANx)
{
    return (((CANx->CTRL1 & CAN_CTRL1_TSFF_Msk) >> CAN_CTRL1_TSFF_Pos) != 0U);
}

/*!
 * @brief Get CAN Receiver status.
 *
 * @param[in] CANx: CAN module
 * @return Receiver status
 */
__STATIC_INLINE uint32_t CAN_GetRStat(CAN_Type *CANx)
{
    return ((CANx->CTRL0 & CAN_CTRL0_RSTAT_Msk) >> CAN_CTRL0_RSTAT_Pos);
}

/*!
 * @brief Get CAN Reception buffer overflow.
 *
 * @param[in] CANx: CAN module
 * @return Reception buffer overflow
 */
__STATIC_INLINE uint32_t CAN_GetRov(CAN_Type *CANx)
{
    return ((CANx->CTRL0 & CAN_CTRL0_ROV_Msk) >> CAN_CTRL0_ROV_Pos);
}

/*!
 * @brief Get CAN kind of error.
 *
 * @param[in] CANx: CAN module
 * @return Kind of error
 */
__STATIC_INLINE uint32_t CAN_GetKoer(CAN_Type *CANx)
{
    return ((CANx->ERRINFO & CAN_ERRINFO_KOER_Msk) >> CAN_ERRINFO_KOER_Pos);
}

/*!
 * @brief Set CAN FD ISO state.
 *
 * @param[in] CANx: CAN module
 * @param[in] state: enable state
 *              - ENABLE
 *              - DISABLE
 * @return none
 */
__STATIC_INLINE void CAN_SetFdIso(CAN_Type *CANx, ACTION_Type state)
{
   MODIFY_REG32(CANx->CTRL0, CAN_CTRL0_FDISO_Msk, CAN_CTRL0_FDISO_Pos, state);
}

/*!
 * @brief Set transmit secondary mode.
 *
 * @param[in] CANx: CAN module
 * @param[in] tsMode: Transmit secondary: operation mode
 *              - CAN_TSMODE_FIFO
 *              - CAN_TSMODE_PRIORITY
 * @return none
 */
__STATIC_INLINE void CAN_SetTSMode(CAN_Type *CANx, CAN_TransmitModeType tsMode)
{
    MODIFY_REG32(CANx->CTRL0, CAN_CTRL0_TSMODE_Msk, CAN_CTRL0_TSMODE_Pos, tsMode);
}

/*!
 * @brief Set CAN Reception buffer overflow.
 *
 * @param[in] CANx: CAN module
 * @param[in] rom: 1: new message will not be stored, 0: The oldest message will be overwrite 
 *              - CAN_RECV_OVER_WRITE
 *              - CAN_RECV_DISCARD
 * @return none
 */
__STATIC_INLINE void CAN_SetRom(CAN_Type *CANx, CAN_OverflowModeType rom)
{
    MODIFY_REG32(CANx->CTRL0, CAN_CTRL0_ROM_Msk, CAN_CTRL0_ROM_Pos, rom);
}

/*!
 * @brief Enable CAN Self-Acknowledge when LBME = 1.
 *
 * @param[in] CANx: CAN module
 * @param[in] state: enable state
 *              - ENABLE
 *              - DISABLE
 * @return none
 */
__STATIC_INLINE void CAN_SetSack(CAN_Type *CANx, ACTION_Type state)
{
    MODIFY_REG32(CANx->CTRL0, CAN_CTRL0_SACK_Msk, CAN_CTRL0_SACK_Pos, state);
}

/*!
 * @brief Enable CAN TDC.
 *
 * @param[in] CANx: CAN module
 * @param[in] state: enable state
 *              - ENABLE
 *              - DISABLE
 * @return none
 */
__STATIC_INLINE void CAN_SetTdc(CAN_Type *CANx, ACTION_Type state)
{
    MODIFY_REG32(CANx->ERRINFO, CAN_ERRINFO_TDCEN_Msk, CAN_ERRINFO_TDCEN_Pos, state);
}

/*!
 * @brief Set CAN error warning limit.
 *
 * @param[in] CANx: CAN module
 * @param[in] offset: SSP offset
 * @return none
 */
__STATIC_INLINE void CAN_SetSspOffet(CAN_Type *CANx, uint8_t offset)
{
    MODIFY_REG32(CANx->ERRINFO, CAN_ERRINFO_SSPOFF_Msk, CAN_ERRINFO_SSPOFF_Pos, offset & 0x7F);
}

/*!
 * @brief Set CAN TIME-stamping Position.
 *
 * @param[in] CANx: CAN module
 * @param[in] pos: TIME-stamping Position
 *              - CAN_TIME_STAMP_SOF
 *              - CAN_TIME_STAMP_EOF
 * @return none
 */
__STATIC_INLINE void CAN_SetTimePosition(CAN_Type *CANx, CAN_TimeStampPosType pos)
{
    MODIFY_REG32(CANx->ACFCTRL, CAN_ACFCTRL_TIMEPOS_Msk, CAN_ACFCTRL_TIMEPOS_Pos, pos);
}

/*!
 * @brief Enable CAN time stamp.
 *
 * @param[in] CANx: CAN module
 * @param[in] state: enable state
 *              - ENABLE
 *              - DISABLE
 * @return none
 */
__STATIC_INLINE void CAN_EnableTimeStamp(CAN_Type *CANx, ACTION_Type state)
{
    MODIFY_REG32(CANx->ACFCTRL, CAN_ACFCTRL_TIMEEN_Msk, CAN_ACFCTRL_TIMEEN_Pos, state);
}

/*!
 * @brief Set time stamp counter enable.
 *
 * @param[in] CANx: CAN module
 * @param[in] enable: time stamp counter enable state
 * @return none
 */
__STATIC_INLINE void CAN_SetTimeStampCount(CAN_Type *CANx, ACTION_Type enable)
{
    MODIFY_REG32(CANx->ACFCTRL, CAN_ACFCTRL_TCEN_Msk, CAN_ACFCTRL_TCEN_Pos, enable);
}

/*!
 * @brief Set CAN acceptance filter enable.
 *
 * @param[in] CANx: CAN module
 * @param[in] index: filter id
 * @param[in] state: enable or disable
 *              - ENABLE
 *              - DISABLE
 * @return none
 */
__STATIC_INLINE void CAN_SetAcfEn(CAN_Type *CANx, uint8_t index, ACTION_Type state)
{
    if (state)
    {
        CANx->ACFCTRL |= ((1 << index) << CAN_ACFCTRL_ACFEN_Pos);
    }
    else
    {
        CANx->ACFCTRL &= ~((1 << index) << CAN_ACFCTRL_ACFEN_Pos);
    }
}

/*!
 * @brief Set CAN acceptance filter index.
 *
 * @param[in] CANx: CAN module
 * @param[in] index: filter id
 * @return none
 */
__STATIC_INLINE void CAN_SetAcfIndex(CAN_Type *CANx, uint8_t index)
{
    DEVICE_ASSERT(CAN_MAX_FILTER_NUM > index);
    MODIFY_REG32(CANx->ACFCTRL, CAN_ACFCTRL_ACFADR_Msk, CAN_ACFCTRL_ACFADR_Pos, index);
}

/*!
 * @brief Set CAN Filter data code.
 *
 * @param[in] CANx: CAN module
 * @param[in] code: Filter data code
 * @return none
 */
__STATIC_INLINE void CAN_SetAcfCode(CAN_Type *CANx, uint32_t code)
{
    CANx->ACFCTRL &= (~CAN_ACFCTRL_SELMASK_Msk);
    CANx->ACF = (code & CAN_ACF_ACODE_Msk);
}

/*!
 * @brief Set CAN Filter data mask + AIDE + AIDEE.
 *
 * @param[in] CANx: CAN module
 * @param[in] mask: Filter data mask + AIDE + AIDEE
 * @return none
 */
__STATIC_INLINE void CAN_SetAcfMask(CAN_Type *CANx, uint32_t mask)
{
    CANx->ACFCTRL |= CAN_ACFCTRL_SELMASK_Msk;
    CANx->ACF = mask & (CAN_ACF_ACODE_Msk | CAN_ACF_AIDE_Msk | CAN_ACF_AIDEE_Msk);
}

/*!
 * @brief Set VERMEM register.
 *
 * @param[in] CANx: CAN module
 * @param[in] value: VERMEM register value
 * @return none
 */
__STATIC_INLINE void CAN_SetVerMem(CAN_Type *CANx, uint32_t value)
{
    CANx->VERMEM = value;
}

/*!
 * @brief Get VERMEM register.
 *
 * @param[in] CANx: CAN module
 * @return VERMEM register value
 */
__STATIC_INLINE uint32_t CAN_GetVerMem(CAN_Type *CANx)
{
    return CANx->VERMEM;
}

/*!
 * @brief Set memory ECC protect enable.
 *
 * @param[in] CANx: CAN module
 * @param[in] enable: ECC protect enable state
 * @return none
 */
__STATIC_INLINE void CAN_SetMemEcc(CAN_Type *CANx, ACTION_Type enable)
{
    MODIFY_REG32(CANx->VERMEM, CAN_VERMEM_MPEN_Msk, CAN_VERMEM_MPEN_Pos, enable);
}

/*!
 * @brief Set memory ECC interrupt enable mask.
 *
 * @param[in] CANx: CAN module
 * @param[in] IntMask: ECC interrupt enable mask
 * @return none
 */
static inline void CAN_SetEccIntMask(CAN_Type *CANx, uint32_t IntMask)
{
    MODIFY_REG32(CANx->VERMEM, (CAN_VERMEM_MDWIE_Msk | CAN_VERMEM_MDEIE_Msk), 0, IntMask);
}

/*!
 * @brief Get memory ECC protect enable state.
 *
 * @param[in] CANx: CAN module
 * @return ECC protect enable state
 */
__STATIC_INLINE uint8_t CAN_GetEccState(CAN_Type *CANx)
{
    return (((CANx->VERMEM & CAN_VERMEM_MPEN_Msk) >> CAN_VERMEM_MPEN_Pos) != 0U);
}

/*!
 * @brief Check memory ECC is initialized done.
 *
 * @param[in] CANx: CAN module
 * @return CAN memory initialization status
 */
__STATIC_INLINE uint8_t CAN_IsMemInitDone(CAN_Type *CANx)
{
    return (((CANx->VERMEM & CAN_VERMEM_MEID_Msk) >> CAN_VERMEM_MEID_Pos) != 0U);
}


/*!
 * @brief Get CAN version.
 *
 * @param[in] CANx: CAN module
 * @return CAN version
 */
__STATIC_INLINE uint16_t CAN_GetVersion(CAN_Type *CANx)
{
    return (CANx->VERMEM & CAN_VERMEM_VERSION_Msk);
}

/*!
 * @brief Get receive error count.
 *
 * @param[in] CANx: CAN module
 * @return receive error count
 */
__STATIC_INLINE uint8_t CAN_GetRECnt(CAN_Type *CANx)
{
    return ((CANx->ERRINFO & CAN_ERRINFO_RECNT_Msk) >> CAN_ERRINFO_RECNT_Pos);
}

/*!
 * @brief Get transmit error count.
 *
 * @param[in] CANx: CAN module
 * @return transmit error count
 */
__STATIC_INLINE uint8_t CAN_GetTECnt(CAN_Type *CANx)
{
    return ((CANx->ERRINFO & CAN_ERRINFO_TECNT_Msk) >> CAN_ERRINFO_TECNT_Pos);
}

/*!
 * @brief Set CAN normal slow bitrate.
 *
 * @param[in] CANx: CAN module
 * @param[in] bitrate: pointer to bitrate configuration
 * @return none
 */
static inline void CAN_SetSlowBitrate(CAN_Type *CANx, const CAN_BitrateConfigType *bitrate)
{
    DEVICE_ASSERT(bitrate != NULL);

    CANx->SBITRATE = *(uint32_t *)bitrate;
}

/*!
 * @brief Get CAN normal slow bitrate.
 *
 * @param[in] CANx: CAN module
 * @param[in] bitrate: pointer to bitrate configuration
 * @return none
 */
__STATIC_INLINE void CAN_GetSlowBitrate(CAN_Type *CANx, CAN_BitrateConfigType *bitrate)
{
    DEVICE_ASSERT(bitrate != NULL);

    bitrate->SEG_1 = (CANx->SBITRATE & CAN_SBITRATE_S_SEG_1_Msk) >> CAN_SBITRATE_S_SEG_1_Pos;
    bitrate->SEG_2 = (CANx->SBITRATE & CAN_SBITRATE_S_SEG_2_Msk) >> CAN_SBITRATE_S_SEG_2_Pos;
    bitrate->SJW =   (CANx->SBITRATE & CAN_SBITRATE_S_SJW_Msk) >> CAN_SBITRATE_S_SJW_Pos;
    bitrate->PRESC = (CANx->SBITRATE & CAN_SBITRATE_S_PRESC_Msk) >> CAN_SBITRATE_S_PRESC_Pos;
}

/*!
 * @brief Set CAN FD data bitrate.
 *
 * @param[in] CANx: CAN module
 * @param[in] bitrate: pointer to bitrate configuration
 * @return none
 */
__STATIC_INLINE void CAN_SetFastBitrate(CAN_Type *CANx, const CAN_BitrateConfigType *bitrate)
{
    DEVICE_ASSERT(bitrate != NULL);

    CANx->FBITRATE = *(uint32_t *)bitrate;
}

/*!
 * @brief Get CAN FD data bitrate.
 *
 * @param[in] CANx: CAN module
 * @param[in] bitrate: pointer to bitrate configuration
 * @return none
 */
__STATIC_INLINE void CAN_GetFastBitrate(CAN_Type *CANx, CAN_BitrateConfigType *bitrate)
{
    DEVICE_ASSERT(bitrate != NULL);

    bitrate->SEG_1 = (CANx->FBITRATE & CAN_FBITRATE_F_SEG_1_Msk) >> CAN_FBITRATE_F_SEG_1_Pos;
    bitrate->SEG_2 = (CANx->FBITRATE & CAN_FBITRATE_F_SEG_2_Msk) >> CAN_FBITRATE_F_SEG_2_Pos;
    bitrate->SJW =   (CANx->FBITRATE & CAN_FBITRATE_F_SJW_Msk) >> CAN_FBITRATE_F_SJW_Pos;
    bitrate->PRESC = (CANx->FBITRATE & CAN_FBITRATE_F_PRESC_Msk) >> CAN_FBITRATE_F_PRESC_Pos;
}

/*!
 * @brief Set listen only mode.
 *
 * @param[in] CANx: CAN module
 * @param[in] enable: LOM mode
 * @return none
 */
__STATIC_INLINE void CAN_SetListenOnlyMode(CAN_Type *CANx, ACTION_Type enable)
{
    MODIFY_REG32(CANx->CTRL0, CAN_CTRL0_LOM_Msk, CAN_CTRL0_LOM_Pos, enable);
}

/*!
 * @brief Set loopback internal mode.
 *
 * @param[in] CANx: CAN module
 * @param[in] enable: LBMI mode
 * @return none
 */
__STATIC_INLINE void CAN_SetLoopbackIntMode(CAN_Type *CANx, ACTION_Type enable)
{
    MODIFY_REG32(CANx->CTRL0, CAN_CTRL0_LBMI_Msk, CAN_CTRL0_LBMI_Pos, enable);
}

/*!
 * @brief Set loopback external mode.
 *
 * @param[in] CANx: CAN module
 * @param[in] enable: LBME mode
 * @return none
 */
__STATIC_INLINE void CAN_SetLoopbackExtMode(CAN_Type *CANx, ACTION_Type enable)
{
    MODIFY_REG32(CANx->CTRL0, CAN_CTRL0_LBME_Msk, CAN_CTRL0_LBME_Pos, enable);
}

/*!
 * @brief Set automatic recovering from bus off disable state.
 *
 * @param[in] CANx: CAN module
 * @param[in] enable: bus off recovery disable state
 * @return none
 */
__STATIC_INLINE void CAN_SetBusOffRecDisable(CAN_Type *CANx, ACTION_Type enable)
{
    MODIFY_REG32(CANx->CTRL0, CAN_CTRL0_BOREC_Msk, CAN_CTRL0_BOREC_Pos, enable);
}

/*!
 * @brief Check CAN bus idle status.
 *
 * @param[in] CANx: CAN module
 * @return Bus idle status
 */
__STATIC_INLINE uint8_t CAN_IsIdle(CAN_Type *CANx)
{
    return (((CANx->CTRL0 & CAN_CTRL0_IDLE_Msk) >> CAN_CTRL0_IDLE_Pos) != 0U);
}

/*!
 * @brief Get transceiver standby state.
 *
 * @param[in] CANx: CAN module
 * @return Standby state
 */
__STATIC_INLINE uint8_t CAN_GetStandbyState(CAN_Type *CANx)
{
    return (((CANx->CTRL0 & CAN_CTRL0_STBY_Msk) >> CAN_CTRL0_STBY_Pos) != 0U);
}

/*!
 * @brief Set receive buffer store all data frames.
 *
 * @param[in] CANx: CAN module
 * @param[in] enable: receive buffer store all data frames state
 * @return none
 */
__STATIC_INLINE void CAN_SetRball(CAN_Type *CANx, ACTION_Type enable)
{
    MODIFY_REG32(CANx->CTRL0, CAN_CTRL0_RBALL_Msk, CAN_CTRL0_RBALL_Pos, enable);
}

/*!
 * @brief Set memory error bit position 1.
 *
 * @param[in] CANx: CAN module
 * @param[in] position: memory error bit postion 1
 * @return none
 */
__STATIC_INLINE void CAN_SetMebp1(CAN_Type *CANx, uint8_t position)
{
    MODIFY_REG32(CANx->MEMES, CAN_MEMES_MEBP1_Msk, CAN_MEMES_MEBP1_Pos, position);
}

/*!
 * @brief Set memory 1st error enable.
 *
 * @param[in] CANx: CAN module
 * @param[in] enable: memory 1st error enable state
 * @return none
 */
__STATIC_INLINE void CAN_SetMe1ee(CAN_Type *CANx, ACTION_Type enable)
{
    MODIFY_REG32(CANx->MEMES, CAN_MEMES_ME1EE_Msk, CAN_MEMES_ME1EE_Pos, enable);
}

/*!
 * @brief Set memory error bit position 2.
 *
 * @param[in] CANx: CAN module
 * @param[in] position: memory error bit postion 2
 * @return none
 */
__STATIC_INLINE void CAN_SetMebp2(CAN_Type *CANx, uint8_t position)
{
    MODIFY_REG32(CANx->MEMES, CAN_MEMES_MEBP2_Msk, CAN_MEMES_MEBP2_Pos, position);
}

/*!
 * @brief Set memory 2nd error enable.
 *
 * @param[in] CANx: CAN module
 * @param[in] enable: memory 2nd error enable state
 * @return none
 */
__STATIC_INLINE void CAN_SetMe2ee(CAN_Type *CANx, ACTION_Type enable)
{
    MODIFY_REG32(CANx->MEMES, CAN_MEMES_ME2EE_Msk, CAN_MEMES_ME2EE_Pos, enable);
}

/*!
 * @brief Get memory ECC error status.
 *
 * @param[in] CANx: CAN module
 * @return ECC error status
 */
__STATIC_INLINE uint8_t CAN_GetEccStatus(CAN_Type *CANx)
{
    return (uint8_t)((CANx->VERMEM & (CAN_VERMEM_ACFA_Msk | CAN_VERMEM_TXS_Msk | \
        CAN_VERMEM_HELOC_Msk)) >> CAN_VERMEM_ACFA_Pos);
}

/*!
 * @brief Set memory error counter.
 *
 * @param[in] CANx: CAN module
 * @param[in] count: memory error counter
 * @return none
 */
__STATIC_INLINE void CAN_SetMeeec(CAN_Type *CANx, uint8_t count)
{
    MODIFY_REG32(CANx->MEMES, CAN_MEMES_MEEEC_Msk, CAN_MEMES_MEEEC_Pos, count);
}

/*!
 * @brief Set memory no error counter.
 *
 * @param[in] CANx: CAN module
 * @param[in] count: memory no error counter
 * @return none
 */
__STATIC_INLINE void CAN_SetMenec(CAN_Type *CANx, uint8_t count)
{
    MODIFY_REG32(CANx->MEMES, CAN_MEMES_MENEC_Msk, CAN_MEMES_MENEC_Pos, count);
}

/*!
 * @brief Set memory error side.
 *
 * @param[in] CANx: CAN module
 * @param[in] side: memory error side
 * @return none
 */
__STATIC_INLINE void CAN_SetMes(CAN_Type *CANx, uint8_t side)
{
    MODIFY_REG32(CANx->MEMES, CAN_MEMES_MES_Msk, CAN_MEMES_MES_Pos, side);
}

/*!
 * @brief Set memory error location.
 *
 * @param[in] CANx: CAN module
 * @param[in] location: memory error location
 * @return none
 */
__STATIC_INLINE void CAN_SetMel(CAN_Type *CANx, uint8_t location)
{
    MODIFY_REG32(CANx->MEMES, CAN_MEMES_MEL_Msk, CAN_MEMES_MEL_Pos, location);
}

/*!
 * @brief Get arbitration lost capture.
 *
 * @param[in] CANx: CAN module
 * @return Arbitration lost capture position
 */
__STATIC_INLINE uint8_t CAN_GetArbitLostCap(CAN_Type *CANx)
{
    return (uint8_t)((CANx->ERRINFO & CAN_ERRINFO_ALC_Msk) >> CAN_ERRINFO_ALC_Pos);
}

/*!
 * @brief Get error passive flag.
 *
 * @param[in] CANx: CAN module
 * @return Error passive flag
 */
__STATIC_INLINE uint8_t CAN_GetErrorPassiveFlag(CAN_Type *CANx)
{
    return (((CANx->CTRL1 & CAN_CTRL1_EPASS_Msk) >> CAN_CTRL1_EPASS_Pos) != 0U);
}

/*!
 * @brief Get error warning limit flag.
 *
 * @param[in] CANx: CAN module
 * @return Error warning limit flag
 */
__STATIC_INLINE uint8_t CAN_GetErrorWarningFlag(CAN_Type *CANx)
{
    return (((CANx->CTRL1 & CAN_CTRL1_EWARN_Msk) >> CAN_CTRL1_EWARN_Pos) != 0U);
}

#ifdef __cplusplus
}
#endif

#endif /* _AC780X_CAN_REG_H */

/* =============================================  EOF  ============================================== */
